home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -in_the_mag- / multitasking / feature / snoopdos / snoopdos_source / hotkey.c < prev    next >
C/C++ Source or Header  |  2000-03-02  |  12KB  |  483 lines

  1. /*
  2.  *        HOTKEY.C                                                vi:ts=4
  3.  *
  4.  *      Copyright (c) Eddy Carroll, September 1994.
  5.  *
  6.  *        Controls the management of the commodities hotkey for SnoopDos,
  7.  *        along with other related stuff (Workbench AppIcon/Tools Menu support).
  8.  */
  9.  
  10. #include "system.h"
  11. #include "snoopdos.h"
  12. #include "snooptext.h"
  13.  
  14. #include "icon.h"
  15.  
  16. extern char CommodityTitle[];    /* From SNOOPDOS.C */
  17.  
  18. struct NewBroker MyBroker = {
  19.     NB_VERSION,
  20.     "SnoopDos",
  21.     CommodityTitle,
  22.     NULL,                        /* Description, filled in at run time */
  23.     NBU_UNIQUE | NBU_NOTIFY,
  24.     COF_SHOW_HIDE,
  25.     0, 0, 0
  26. };
  27.  
  28. struct MsgPort        *BrokerMP;        /* Message port used for msgs from CX    */
  29. CxObj                *Broker;        /* CX handle for the broker we created    */
  30. CxObj                *Filter;        /* Filter to filter CX messages            */
  31. struct MsgPort        *WorkbenchPort;    /* Port for AppIcon/AppMenu messages    */
  32. struct DiskObject    *ProgramIcon;    /* Handle on our program's icon data    */
  33. struct AppMenuItem    *MyAppMenu;        /* Current AppMenuItem, if any            */
  34. struct AppIcon        *MyAppIcon;        /* Current AppMenuItem, if any            */
  35. struct DiskObject    *AppIconObj;    /* Current object for AppMenuItem        */    
  36. struct DiskObject    *DefIconObj;    /* A temporary default icon we use        */    
  37.  
  38. /*
  39.  *        InstallHotKey(char *hotkey)
  40.  *
  41.  *        Initialises commodity support and sets things up so that the
  42.  *        key sequence specified by "hotkey" will send a CTRL-F activation
  43.  *        signal to SnoopDos. We can also get various messages from the
  44.  *        commodities exchange to show/hide the interface etc -- these
  45.  *        will be indicated using CommodityMask.
  46.  *
  47.  *        To see whether a hotkey is currently available or not, simply
  48.  *        check the HotKeyActive flag. (This is used for disabling window
  49.  *        gadgets etc.)
  50.  *
  51.  *        Returns true for success, false for failure.
  52.  */
  53. int InstallHotKey(char *hotkey)
  54. {
  55.     CxObj *newobj;
  56.  
  57.     HotKeyActive = 0;        /* Assume commodity is not currently active */
  58.  
  59.     if (CurSettings.Setup.HideMethod == HIDE_NONE || !CxBase) {
  60.         /*
  61.          *        Don't install a commodity at all if we have no hide
  62.          *        method.
  63.          */
  64.         return (0);
  65.     }
  66.     if (!BrokerMP) {
  67.         BrokerMP = CreateMsgPort();
  68.         if (!BrokerMP)
  69.             return (0);
  70.         CommodityMask      = (1L << BrokerMP->mp_SigBit);
  71.     }
  72.  
  73.     if (Broker && MyBroker.nb_Pri != CommodityPriority) {
  74.         /*
  75.          *        The commodity priority has changed, so 
  76.          *        remove the current broker to force a new
  77.          *        one to be created at the correct priority.
  78.          */
  79.         DeleteCxObjAll(Broker);
  80.         Broker = NULL;
  81.         Filter = NULL;
  82.     }
  83.     if (!Broker) {
  84.         /*
  85.          *        Attempt to create a new broker
  86.          */
  87.         MyBroker.nb_Descr = MSG(MSG_COMMODITY_DESC);
  88.         MyBroker.nb_Port  = BrokerMP;
  89.         MyBroker.nb_Pri   = CommodityPriority;
  90.         Broker = CxBroker(&MyBroker, NULL);
  91.         if (!Broker)
  92.             return (0);
  93.         ActivateCxObj(Broker, 1);
  94.     }
  95.     /*
  96.      *        Okay, now we create a new filter object to handle the
  97.      *        commodity string we were passed
  98.      */
  99.     if (Filter)
  100.         DeleteCxObjAll(Filter);
  101.     
  102.     Filter = CxFilter(hotkey);
  103.     if (!Filter) {
  104.         /*
  105.          *        Couldn't create the filter (probably out of memory --
  106.          *        specifying an illegal hotkey doesn't cause this to
  107.          *        fail, but instead produces an accumulated error later).
  108.          *
  109.          *        We still leave the broker itself installed, since it can
  110.          *        be used to allow the CX to send us Enable/Disable/Show/
  111.          *        Hide/Quit messages.
  112.          */
  113.         return (0);
  114.     }
  115.  
  116.     /*
  117.      *        Now add our various translation bits and pieces to the filter
  118.      */
  119.     newobj = CxSignal(SysBase->ThisTask, SIGBREAKB_CTRL_F);
  120.     if (!newobj)
  121.         goto filter_error;
  122.     AttachCxObj(Filter, newobj);
  123.  
  124.     newobj = CxTranslate(NULL);
  125.     if (!newobj)
  126.         goto filter_error;
  127.     AttachCxObj(Filter, newobj);
  128.  
  129.     if (CxObjError(Filter))
  130.         goto filter_error;
  131.  
  132.     AttachCxObj(Broker, Filter);
  133.     HotKeyActive = 1;    /* Everything went okay so show we're active */
  134.     return (1);
  135.  
  136. filter_error:
  137.     DeleteCxObjAll(Filter);
  138.     Filter = NULL;
  139.     return (NULL);
  140. }
  141.  
  142. /*
  143.  *        HandleHotKey()
  144.  *
  145.  *        Handles any incoming messages on the commodities exchange port.
  146.  *        Should be called whenever a CommodityMask signal is received.
  147.  */
  148. void HandleHotKeyMsgs(void)
  149. {
  150.     CxMsg *msg;
  151.  
  152.     if (!BrokerMP)
  153.         return;
  154.  
  155.     while ((msg = (CxMsg *)GetMsg(BrokerMP)) != NULL) {
  156.         ULONG msgid        = CxMsgID(msg);
  157.         ULONG msgtype    = CxMsgType(msg);
  158.  
  159.         ReplyMsg((void *)msg);
  160.         if (msgtype == CXM_COMMAND) {
  161.             switch (msgid) {
  162.                 
  163.                 case CXCMD_DISABLE:
  164.                     SetMonitorMode(MONITOR_DISABLED);
  165.                     break;
  166.  
  167.                 case CXCMD_ENABLE:
  168.                     if (Disabled)    /* Don't want to enable if Paused */
  169.                         SetMonitorMode(MONITOR_NORMAL);
  170.                     break;
  171.  
  172.                 case CXCMD_KILL:
  173.                     QuitFlag = 1;
  174.                     break;
  175.  
  176.                 case CXCMD_APPEAR:
  177.                 case CXCMD_UNIQUE:
  178.                     ShowSnoopDos();
  179.                     break;
  180.  
  181.                 case CXCMD_DISAPPEAR:
  182.                     HideSnoopDos();
  183.                     break;
  184.             }
  185.         }
  186.     }
  187. }
  188.  
  189. /*
  190.  *        CleanupHotKey()
  191.  *
  192.  *        Frees any resources used by the commodities module
  193.  */
  194. void CleanupHotKey(void)
  195. {
  196.     if (Broker) {
  197.         DeleteCxObjAll(Broker);
  198.         Broker = NULL;
  199.         Filter = NULL;
  200.     }
  201.     if (BrokerMP) {
  202.         struct Message *msg;
  203.         while ((msg = GetMsg(BrokerMP)) != NULL)
  204.             ReplyMsg(msg);
  205.         DeleteMsgPort(BrokerMP);
  206.         BrokerMP      = NULL;
  207.         CommodityMask = 0;
  208.     }
  209.     HotKeyActive = 0;
  210. }
  211.  
  212. /*
  213.  *        GetCommandName()
  214.  *
  215.  *        Returns a pointer to a static string containing the name of
  216.  *        this program. The pointer remains valid until the next call
  217.  *        to this function.
  218.  */
  219. char *GetCommandName(void)
  220. {
  221.     static char name[200];
  222.     struct Process *pr = (struct Process *)SysBase->ThisTask;
  223.     struct CommandLineInterface *cli = BTOC(pr->pr_CLI);
  224.     char *cmdname = (char *)BTOC(cli->cli_CommandName);
  225.  
  226.     if (WBenchMsg)
  227.         return (WBenchMsg->sm_ArgList->wa_Name);
  228.     
  229.     memcpy(name, cmdname+1, *cmdname);
  230.     name[*cmdname] = '\0';
  231.     return (name);
  232. }
  233.  
  234. /*
  235.  *        GetProgramIcon()
  236.  *
  237.  *        Returns a pointer to an icon structure containing a program
  238.  *        icon for SnoopDos, as follows:
  239.  *
  240.  *            If SnoopDos was run from Workbench, we have a lock on it
  241.  *            If SnoopDos was run from CLI, we look in the directory
  242.  *            the program was run from. If we can't find it there, then
  243.  *            we give up and use the default SnoopDos icon image.
  244.  *
  245.  *        Regardless, you should call CleanupIcons() before exiting,
  246.  *        to free up any loose icon images that may have been allocated.
  247.  *
  248.  *        Warning: icon.library must be open when you call this function.
  249.  */
  250. struct DiskObject *GetProgramIcon(void)
  251. {
  252.     if (ProgramIcon)
  253.         return (ProgramIcon);
  254.     
  255.     if (WBenchMsg) {
  256.         /*
  257.          *        Running from Workbench, so try and get the program icon
  258.          *        indicated in the lock
  259.          */
  260.         struct WBArg *wbarg = WBenchMsg->sm_ArgList;
  261.         BPTR lk;
  262.  
  263.         lk          = CurrentDir(wbarg->wa_Lock);
  264.         ProgramIcon = GetDiskObject(wbarg->wa_Name);
  265.         CurrentDir(lk);
  266.     } else {
  267.         /*
  268.          *        Running from CLI so try and get icon associated with executable
  269.          */
  270.         struct Process *pr = (struct Process *)SysBase->ThisTask;
  271.         BPTR lk;
  272.  
  273.         if (pr->pr_HomeDir)    
  274.             lk = CurrentDir(pr->pr_HomeDir);
  275.         ProgramIcon = GetDiskObject(GetCommandName());
  276.         if (pr->pr_HomeDir)
  277.             CurrentDir(lk);
  278.     }
  279.     if (ProgramIcon)
  280.         return (ProgramIcon);
  281.     
  282.     /*
  283.      *        Okay, unfortunately we couldn't locate the program icon, so
  284.      *        instead, let's just fall back to the default icon.
  285.      */
  286.     DefSnoopDosIcon.do_StackSize = MINSTACKSIZE;    /* Fix this up here */
  287.     return (&DefSnoopDosIcon);
  288. }
  289.  
  290. /*
  291.  *        CleanupIcons()
  292.  *
  293.  *        Frees any icon-related resources that were allocated
  294.  */
  295. void CleanupIcons(void)
  296. {
  297.     RemoveProgramFromWorkbench();
  298.     if (ProgramIcon) {
  299.         FreeDiskObject(ProgramIcon);
  300.         ProgramIcon = NULL;
  301.     }
  302.     if (DefIconObj) {
  303.         FreeDiskObject(DefIconObj);
  304.         DefIconObj = NULL;
  305.         AppIconObj = NULL;
  306.     }
  307.     if (WorkbenchPort) {
  308.         struct Message *msg;
  309.  
  310.         while ((msg = GetMsg(WorkbenchPort)) != NULL)
  311.             ReplyMsg(msg);
  312.  
  313.         DeleteMsgPort(WorkbenchPort),
  314.         WorkbenchPort = NULL;
  315.         WorkbenchMask = 0;
  316.     }
  317.     if (WorkbenchBase) {
  318.         CloseLibrary(WorkbenchBase);
  319.         WorkbenchBase = NULL;
  320.     }
  321. }
  322.  
  323. /*
  324.  *        WriteIcon(filename)
  325.  *
  326.  *        Writes a SnoopDos project icon to the associated filename. If an
  327.  *        icon already exists for the filename, then that icon is left alone.
  328.  *
  329.  *        If no icon exists, then we create one using a copy of what we think
  330.  *        is the icon SnoopDos was started from (or the default).
  331.  */
  332. void WriteIcon(char *filename)
  333. {
  334.     struct DiskObject newobj;
  335.     struct DiskObject *dobj;
  336.  
  337.     if (!IconBase)
  338.         return;
  339.     
  340.     dobj = GetDiskObject(filename);
  341.     if (dobj) {
  342.         FreeDiskObject(dobj);
  343.         return;
  344.     }
  345.     dobj = GetProgramIcon();
  346.  
  347.     /*
  348.      *        We can create a copy of our tool icon and change
  349.      *        it to a project icon.
  350.      */
  351.     newobj = *dobj;
  352.     newobj.do_CurrentX      = NO_ICON_POSITION;
  353.     newobj.do_CurrentY      = NO_ICON_POSITION;
  354.     newobj.do_ToolTypes     = DefToolTypes;
  355.     newobj.do_Type            = WBPROJECT;
  356.     if (WBenchMsg)
  357.         newobj.do_DefaultTool = WBenchMsg->sm_ArgList->wa_Name;
  358.     else
  359.         newobj.do_DefaultTool = GetCommandName();
  360.     PutDiskObject(filename, &newobj);
  361. }
  362.  
  363. /*
  364.  *        AddProgramToWorkbench(hidetype)
  365.  *
  366.  *        Creates an AppIcon or AppMenuItem which can be used to re-active
  367.  *        SnoopDos, and attaches it to Workbench. Normally used when
  368.  *        SnoopDos goes into a HIDE state.
  369.  *
  370.  *        Hidetype is HIDE_ICON or HIDE_TOOLS, depending on which type of
  371.  *        hide method is required.
  372.  *
  373.  *        Initialises WorkbenchMask accordingly.
  374.  *
  375.  *        Call RemoveProgramFromWorkbench() to remove the item later on.
  376.  *
  377.  *        Returns TRUE for success, FALSE for failure.
  378.  */
  379. int AddProgramToWorkbench(int hidetype)
  380. {
  381.     if (!IconBase)
  382.         return (FALSE);
  383.  
  384.     if (!WorkbenchBase) {
  385.         WorkbenchBase = OpenLibrary("workbench.library", 37);
  386.         if (!WorkbenchBase)
  387.             return (FALSE);
  388.     }
  389.     if (!WorkbenchPort) {
  390.         WorkbenchPort = CreateMsgPort();
  391.         if (!WorkbenchPort)
  392.             return (FALSE);
  393.         WorkbenchMask = (1 << WorkbenchPort->mp_SigBit);
  394.     }
  395.     if (hidetype == HIDE_TOOLS && !MyAppMenu) {
  396.         /*
  397.          *        Adding an item to the Workbench tools menu
  398.          */
  399.         MyAppMenu = AddAppMenuItem(0, 0, MSG(MSG_APPMENU_NAME),
  400.                                    WorkbenchPort, NULL);
  401.         if (!MyAppMenu)
  402.             return (FALSE);
  403.     }
  404.     if (hidetype == HIDE_ICON && !MyAppIcon) {
  405.         /*
  406.          *        Adding an AppIcon to the Workbench. We make a copy
  407.          *        of the current program icon to use as our appicon.
  408.          */
  409.         struct DiskObject *dobj;
  410.  
  411.         if (!AppIconObj) {
  412.             /*
  413.              *        We need a temporary icon to play around with.
  414.              *        We allocate a new default disk object, copy
  415.              *        it, and modify our copy to give us an icon
  416.              *        we can use as an AppIcon. We need to remember
  417.              *        to free the original icon before we exit.
  418.              */
  419.             static struct DiskObject defobj;
  420.                 
  421.             DefIconObj = GetDefDiskObject(WBTOOL);
  422.             if (!DefIconObj)
  423.                 return (FALSE);
  424.  
  425.             defobj     = *DefIconObj;
  426.             AppIconObj = &defobj;
  427.             dobj       = GetProgramIcon();
  428.  
  429.             AppIconObj->do_Gadget.Width            = dobj->do_Gadget.Width;
  430.             AppIconObj->do_Gadget.Height        = dobj->do_Gadget.Height;
  431.             AppIconObj->do_Gadget.Flags            = dobj->do_Gadget.Flags;
  432.             AppIconObj->do_Gadget.GadgetRender    = dobj->do_Gadget.GadgetRender;
  433.             AppIconObj->do_Gadget.SelectRender    = dobj->do_Gadget.SelectRender;
  434.             AppIconObj->do_Type                   = 0;
  435.         }
  436.         AppIconObj->do_CurrentX    = CurSettings.IconPosLeft != -1 ?
  437.                                   CurSettings.IconPosLeft :
  438.                                   NO_ICON_POSITION;
  439.         AppIconObj->do_CurrentY    = CurSettings.IconPosTop != -1 ?
  440.                                   CurSettings.IconPosTop :
  441.                                   NO_ICON_POSITION;
  442.         MyAppIcon = AddAppIcon(0, 0, APPICON_NAME, WorkbenchPort,
  443.                                NULL, AppIconObj, TAG_DONE);
  444.         if (!MyAppIcon)
  445.             return (FALSE);
  446.     }
  447.     return (TRUE);
  448. }
  449.  
  450. /*
  451.  *        RemoveProgramFromWorkbench()
  452.  *
  453.  *        Removes any AppIcon or AppMenuItem item that is currently installed
  454.  *        on Workbench. Usually called when the SnoopDos window is about
  455.  *        about to reappear.
  456.  */
  457. void RemoveProgramFromWorkbench(void)
  458. {
  459.     if (MyAppMenu)        RemoveAppMenuItem(MyAppMenu),    MyAppMenu = NULL;
  460.     if (MyAppIcon)        RemoveAppIcon(MyAppIcon),        MyAppIcon = NULL;
  461. }
  462.  
  463. /*
  464.  *        HandleWorkbenchMsgs()
  465.  *
  466.  *        Handles any outstanding messages at the Workbench message port
  467.  */
  468. void HandleWorkbenchMsgs(void)
  469. {
  470.     struct AppMessage *msg;
  471.     int show = 0;
  472.  
  473.     if (!WorkbenchPort)
  474.         return;
  475.     
  476.     while ((msg = (void *)GetMsg(WorkbenchPort)) != NULL) {
  477.         show = 1;
  478.         ReplyMsg(msg);
  479.     }
  480.     if (show)
  481.         ShowSnoopDos();
  482. }
  483.